package com.hyperplan.neptune.parser.generic;

import java.util.ArrayList;
import java.util.List;

import com.hyperplan.neptune.lexer.Token;

public class ListParser<T> implements Parser<T[]> {

	private Parser<T> elementParser;
	private Parser<?> delimiterParser;
	
	public ListParser(Parser<T> elementParser, Parser<?> delimiterParser) {
		this.elementParser = elementParser;
		this.delimiterParser = delimiterParser;
	}
	
	public ListParser(Parser<T> elementParser) {
		this(elementParser, null);
	}
	
	public ParserSolution<T[]> parse(List<Token> tokens, int index)
			throws ParserException {
		List<T> elements = null;
		boolean checkElement = true;
		for (; index <= tokens.size(); index++) {
			if (checkElement) {
				try {
					ParserSolution<T> solution = elementParser.parse(tokens, index);
					if (elements == null) {
						elements = new ArrayList<T>();
					}
					elements.add(solution.getElement());
					index = solution.getIndex();
					if (delimiterParser != null) {
						checkElement = false;
					}
				}
				catch (ParserException exception) {
					if (delimiterParser != null) {
						throw exception;
					} else if (elements == null) {
						throw exception;
					} else {
						break;
					}
				}
			} else {
				try {
					ParserSolution<?> solution = delimiterParser.parse(tokens, index);
					index = solution.getIndex();
					checkElement = true;
				}
				catch (ParserException exception) {
					if (elements == null) {
						throw exception;
					} else {
						break;
					}
				}
			}
		}
		@SuppressWarnings("unchecked")
		T[] result = (T[])elements.toArray();
		return new ParserSolution<T[]>(result, index);
	}
}
